
/*
 * Copyright (C) 2008-2009 Archie L. Cobbs. All rights reserved.
 *
 * $Id$
 */

package org.dellroad.sidekar;

import org.aspectj.lang.reflect.MethodSignature;
import org.dellroad.sidekar.annotation.SidekarEntity;
import org.dellroad.sidekar.annotation.SidekarField;

/**
 * Sidekar AOP aspect.
 */
public aspect SidekarAspect {

    // Private marker interface
    private interface ItemHolder extends Item { };

    // All entity classes should implement the Item interface
    declare parents : (@SidekarEntity *) implements ItemHolder;

    // All Item implementations need an id field
    private long ItemHolder.id;

    // Implement Item.getSidekarId()
    public long ItemHolder.getSidekarId() {
        return this.id;
    }

    public pointcut booleanGetter(ItemHolder item) :
      execution(boolean *()) && this(item) && @annotation(SidekarField);

    public pointcut booleanSetter(ItemHolder item, boolean value) :
      execution(void *(boolean)) && this(item) && args(value) && @annotation(SidekarField);

    boolean around(ItemHolder item) : booleanGetter(item) {
        try {
            return Sidekar.getBooleanFieldValue(thisJoinPointStaticPart, item.id);
        } catch (DetachedItemException e) {
            return proceed(item);
        }
    }

    void around(ItemHolder item, boolean value) : booleanSetter(item, value) {
        try {
            Sidekar.setBooleanFieldValue(thisJoinPointStaticPart, item.id, value);
            return;
        } catch (DetachedItemException e) {
            proceed(item, value);
        }
    }

}

